#!/usr/bin/env python
# encoding: utf-8


"""
@file: mianjij.py
@time: 2016/12/6 上午11:37
"""
# 求三角形面积
from mathsolver.functions.sanjiao.bianjiaozhuanhuan import a, b, c, A, B, C
from sympy import symbols
from mathsolver.functions.base import *
from sympy import sympify, sqrt, FiniteSet, pi, solveset
from mathsolver.functions.sanjiao.bianjiaozhuanhuan import SIDES, ANGLES, JiaoHuaBian, sin, cos, tan, cancel, fraction
from itertools import chain
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao import sanjiaoxing_utils as san_utils
from mathsolver.functions.sanjiao.triangle_constant import TRIANGLE_SHAPR_SEARCH_KEY
from mathsolver.functions.sanjiao.sanjiao_objects import SanJiaoXing

# cos角度的替换
COS_ANGLE_SUBS = (
    (cos(A), (b ** 2 + c ** 2 - a ** 2) / (2 * b * c)),
    (cos(B), (a ** 2 + c ** 2 - b ** 2) / (2 * a * c)),
    (cos(C), (a ** 2 + b ** 2 - c ** 2) / (2 * a * b))
)


# 一些等式求出 a, b, c, cosA, cosB, cosC的值
# 利用求三角形公式  求出三角形面积
class MianJi001(BaseFunction):
    def solver(self, *args):
        self.label.add('求三角形面积')
        eqs = args[0].sympify()
        text = args[1]
        eq_list = []
        eqs_list = []
        du_p = r'du(\(\d+?\))'
        for tmp_eq in eqs:
            l_expr, r_expr = tmp_eq
            tmp_f = l_expr - r_expr
            m = re.search(du_p, str(tmp_f))
            if m:
                du_str = m.group()
                du_sub = sympify(m.groups()[0]) * pi / 180
                tmp_f = tmp_f.subs(du_str, du_sub)
            symbs = list(tmp_f.free_symbols)
            if len(symbs) == 1:  # 如果只含有一个未知变量
                symb = symbs[0]
                if FiniteSet(symb).is_subset(SIDES):  # 如果是边的变量
                    eq_list.append([tmp_f, '0'])
                elif FiniteSet(symb).is_subset(ANGLES):  # 如果是角的变量
                    symb_value = solveset(tmp_f)
                    if isinstance(symb_value, FiniteSet):  # 如果是类似 A = pi/4
                        v = list(symb_value)[0]
                        eq_list.append([(cos(symb) - cos(v)).subs(COS_ANGLE_SUBS), '0'])
                    else:
                        tmp_f = tmp_f.subs(COS_ANGLE_SUBS)
                        if tmp_f.coeff(sin(symb)):  # 如果含有sin的
                            sin_symb_value = solve(tmp_f, sin(symb))[0]
                            if text.find('锐角') >= 0:
                                cos_symb_value = sqrt(1 - sin_symb_value ** 2)
                                eq_list.append([(cos(symb) - cos_symb_value).subs(COS_ANGLE_SUBS), '0'])
                            elif text.find('钝角') >= 0:
                                cos_symb_value = -sqrt(1 - sin_symb_value ** 2)
                                eq_list.append([(cos(symb) - cos_symb_value).subs(COS_ANGLE_SUBS), '0'])
                            else:
                                pass
                        elif tmp_f.coeff(tan(symb)):  # 如果含有tan的
                            tan_symb_value = solve(tmp_f, tan(symb))[0]
                            sin_cos_values = solve(
                                (tan_symb_value * cos(symb) - sin(symb), sin(symb) ** 2 + cos(symb) ** 2 - 1),
                                sin(symb), cos(symb))
                            cos_values = map(lambda _: _[cos(symb)], sin_cos_values)
                            tmp_eqs = map(lambda cv: [(cv - cos(symb)).subs(COS_ANGLE_SUBS), '0'], cos_values)
                            eqs_list.append(BaseEqs(tmp_eqs))
                        else:
                            eq_list.append([tmp_f, 0])
                else:
                    eqs_list.append(JiaoHuaBian(verbose=True).solver(BaseEq([tmp_f, '0'])).output[0])
            elif FiniteSet(*symbs).is_subset(SIDES):
                eq_list.append([tmp_f, '0'])
            else:
                eqs_list.append(JiaoHuaBian(verbose=True).solver(BaseEq([tmp_f, '0'])).output[0])
        eq_list = map(lambda _: [fraction(cancel(sympify(_[0]) - sympify(_[1])))[0], 0], eq_list)
        if eqs_list:
            base_eqs = BaseEqs(eq_list)
            eqs_list = map(lambda _: _.sympify(), eqs_list)
            target_eq_sets_list = co.combin_iters((base_eqs,), *eqs_list)  # 目标方程组可能的列表
            abc_values = []
            for eq_sets in target_eq_sets_list:
                first_eqs = eq_sets[0].sympify()
                tmp_eq_sets = list(chain(first_eqs, eq_sets[1:]))
                tmp_eq_sets = map(lambda _: [fraction(cancel(sympify(_[0]) - sympify(_[1])))[0], 0], tmp_eq_sets)
                try:
                    abc_values.extend(co.solve_poly_eqs(BaseEqs(tmp_eq_sets)))
                except Exception:
                    pass
        else:
            abc_values = co.solve_poly_eqs(BaseEqs(eq_list))
        # ----处理abc的值-------
        # 合法的边
        abc_values = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values)
        # 是否满足两边之和大于第三边
        abc_values = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values)
        for abc_v in abc_values:
            side_values = (abc_v[0][1], abc_v[1][1], abc_v[2][1])
            area = san_utils.triangle_area(side_values)
            self.steps.append(['求得面积', new_latex(area)])
            self.output.append(BaseNumber(area))
        return self


# 根据已知的条件求出a，b，c的值 然后求出三角形面积
class MianJi002(BaseFunction):
    def solver(self, *args):
        self.label.add('求三角形面积')
        tmp_eqs = san_utils.known_triangle_eqs(self.known)
        eqs_list = tmp_eqs.sympify()
        new_eqs = []
        for tmp_eq in eqs_list:
            e_l, e_r = tmp_eq
            e_l = e_l.subs(san_utils.get_triangle_subs())
            e_r = e_r.subs(san_utils.get_triangle_subs())
            new_eqs.append([e_l, e_r])
        new_eqs = BaseEqs(new_eqs)
        eq_sets = SanJiaoXing.simu_trian_eqs(new_eqs)  # 联立方程组
        abc_values_list = []
        self.steps.append(['由题意可利用边角转换 ', ''])
        for base_eqs in eq_sets:
            self.steps.append(['联立方程组', base_eqs.printing()])
            try:
                # abc_values = co.solve_poly_eqs(base_eqs)
                abc_values = co.isolve_eqs(base_eqs, ['a', 'b', 'c'])
                if abc_values:  # 有可能解出来是空集
                    for tmp_set in abc_values:
                        self.steps.append(['求得', BaseEqs(tmp_set).printing()])
                    abc_values_list.extend(abc_values)
            except Exception:
                pass
                # abc_values = co.solve_poly_eqs(base_eqs)
                # for tmp_set in abc_values:
                #     self.steps.append(['求得', BaseEqs(tmp_set).printing()])
                # abc_values_list.extend(abc_values)
        # 合法的边
        abc_values_list = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values_list)
        # 是否满足两边之和大于第三边
        abc_values_list = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values_list)
        # 锐角三角形，钝角三角形 等等条件
        if self.search(TRIANGLE_SHAPR_SEARCH_KEY):
            triangle_type = str(list(self.search(TRIANGLE_SHAPR_SEARCH_KEY))[0])
            if triangle_type == 'acute_triangle':
                abc_values_list = filter(lambda _: san_utils.acute_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
            elif triangle_type == 'obtuse_triangle':
                abc_values_list = filter(lambda _: san_utils.obtuse_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
        a_vs, b_vs, c_vs = [], [], []
        # 还有可能是指定了某个角度的值
        _A, _B, _C = symbols('A, B, C')
        if self.search(_A):
            pass
        elif self.search(_B):
            pass
        elif self.search(_C):
            pass
        self.steps.append(['验证求得:', ''])
        for abc_values in abc_values_list:
            a_v, b_v, c_v = abc_values
            self.steps.append([BaseEqs(abc_values).printing(), ''])
            a_vs.append(a_v[1])
            b_vs.append(b_v[1])
            c_vs.append(c_v[1])
        abc_values_list = list(zip(a_vs, b_vs, c_vs))
        abc_values = abc_values_list[0]
        abc_values = list(zip((sympify('a'), sympify('b'), sympify('c')), abc_values))
        area_expr = sympify('(a+b+c)*(a+b-c)*(a+c-b)*(b+c-a)')
        area_value = area_expr.subs(abc_values)
        area_value = simplify(area_value)
        self.steps.append(['求得面积为:', new_latex(area_value)])
        self.output.append(BaseNumber(area_value))
        return self


# 三角形面积
class SanJiaoXingMianji(BaseFunction):
    CLS = [MianJi002, MianJi001, ]

    def known_eqs(self):
        eqs = map(lambda kv: (kv[0], list(kv[1])[0]), self.known.items())
        arg_eqs = []
        for l_expr, r_expr in eqs:
            f = sympify(l_expr) - sympify(r_expr)
            if FiniteSet(*f.free_symbols).is_subset(FiniteSet(*symbols('A, B, C, a, b, c'))):
                arg_eqs.append([f, '0'])
        return BaseEqs(arg_eqs)

    def solver(self, *args):
        tmp_args = [san_utils.known_triangle_eqs(self.known), ]
        tmp_args.extend([arg for arg in args])
        solve_r = None
        for cl in SanJiaoXingMianji.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r.known = self.known
                solve_r = solve_r.solver(*tmp_args)
                solve_r.label.add('求三角形面积')
                break
            except Exception:
                pass
        if not solve_r:
            raise Exception('try fail')
        return solve_r


if __name__ == '__main__':
    pass
